<template>
  <div class="app-apge">
    <div class="loading" v-if="loading">
        Loading...
    </div>
    <template v-else>
      <div class="canvas" ref="canvas"></div>
      <div id="js-properties-panel" class="panel"></div>
      <div class="buttons">
        <el-button type="primary" @click="saveBpmn">保存为bpmn</el-button>
        <el-button type="success" @click="saveSvg">保存为svg</el-button>
        <a href="javascipt:;" ref="download"></a>
      </div>
    </template>
  </div>
</template>

<script>
// 引入axios用来发送http请求
import axios from 'axios'
// 引入相关的依赖
import BpmnModeler from 'bpmn-js/lib/Modeler'
// 引入一个本地的xml字符串, 若是没有获取到后台的数据则用它
import { xmlStr } from '@/assets/xmlStr'
// 左侧工具栏(导入样式即可): 以下为bpmn工作流绘图工具的样式
import 'bpmn-js/dist/assets/diagram-js.css' // 左边工具栏以及编辑节点的样式
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
// 右侧属性栏
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
export default {
  name: 'BpmnTest3',
  data () {
    return {
      // bpmn建模器
      bpmnModeler: null,
      container: null,
      canvas: null,
      loading: true, // loading效果
      xmlUrl: '', // bpmn文件地址
      defaultXmlStr: xmlStr // 如果后台没有返回xmlUrl，则给一个默认的
    }
  },
  methods: {
    async init () {
      this.loading = true
      try {
        this.xmlUrl = await this.getData()
        this.loading = false
        // 等待 DOM 更新之后再对工作流进行初始化
        this.$nextTick(() => {
          this.initBpmn()
        })
      } catch (error) {
        console.log(error)
      }
    },
    // 模拟请求后台获取bpmn文件地址
    getData () {
      return new Promise(resolve => {
        setTimeout(() => {
          // 模拟网络请求的一个地址
          const url = 'https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn'
          resolve(url)
        }, 1000)
      })
    },
    initBpmn () {
      // 获取到属性ref为“canvas”的dom节点
      const canvas = this.$refs.canvas
      // 建模
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        // 添加控制板
        propertiesPanel: {
          parent: '#js-properties-panel'
        },
        additionalModules: [
          // 左边工具栏以及节点
          propertiesProviderModule,
          // 右边的工具栏
          propertiesPanelModule
        ],
        moddleExtensions: {
          camunda: camundaModdleDescriptor
        }
      })
      this.createNewDiagram()
    },
    async createNewDiagram () {
      const that = this
      let bpmnXmlStr = ''
      if (this.xmlUrl === '') { // 若是后台没有数据则使用默认的一个xml
        bpmnXmlStr = this.defaultXmlStr
        this.transformCanvas(bpmnXmlStr)
      } else {
        const res = await axios({
          method: 'get',
          timeout: 120000,
          url: that.xmlUrl,
          headers: { 'Content-Type': 'multipart/form-data' }
        })
        bpmnXmlStr = res.data
        this.transformCanvas(bpmnXmlStr)
      }
    },
    async transformCanvas (bpmnXmlStr) {
      try {
        // 将字符串转换成图显示出来
        await this.bpmnModeler.importXML(bpmnXmlStr)
        this.success()
        // 让图能自适应屏幕
        var canvas = this.bpmnModeler.get('canvas')
        canvas.zoom('fit-viewport')
      } catch (error) {
        console.log(error)
      }
    },
    success () {
      this.addBpmnListener()
    },
    // 添加绑定事件
    addBpmnListener () {
      // 给图绑定事件，当图有发生改变就会触发这个事件
      this.bpmnModeler.on('commandStack.changed', async () => {
        try {
          const result = await this.bpmnModeler.saveXML({ format: true })
          // eslint-disable-next-line no-unused-vars
          const { xml } = result // xml是最新的xml
        } catch (error) {
          console.log(error)
        }
      })
    },
    // 保存成bpmn
    async saveBpmn () {
      const result = await this.bpmnModeler.saveXML({ format: true })
      const { xml } = result
      this.setEncoded(this.$refs.download, 'test.bpmn', xml)
    },
    // 保存成svg
    async saveSvg () {
      const result = await this.bpmnModeler.saveSVG({ format: true })
      const { svg } = result
      this.setEncoded(this.$refs.download, 'test.svg', svg)
    },
    /**
     * link：a标签，可以通过document.getElementById
     * name：文件名称
     * data：数据
    */
    setEncoded (link, name, data) {
      // 把xml转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data)
      // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
      if (data) {
        link.className = 'active' // 设置这个自动点击
        link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
        link.download = name
        this.$refs.download.click()
      }
    }
  },
  mounted () {
    this.init()
  }
}
</script>

<style lang="scss">
.canvas {
  width: 100%;
  height: 100%;
}
.panel{
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}
.bjs-powered-by{
  display: none !important;
}
.buttons {
  position: absolute;
  left: 20px;
  bottom: 20px;
}
</style>
